package fischl.web;

import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import fischl.log.Log;
import fischl.log.LogFactory;
import okhttp3.internal.Util;
import okio.BufferedSource;
import okio.Okio;

public final class TemplateEngine {
  private static final Log log = LogFactory.get("template");
  private static final Map<String, String> cache = new ConcurrentHashMap<>();

  public static String render(String templateName, Map<String, Object> models) {
    String template = cache.get(templateName);
    if (template == null) {
      template = loadTemplate(templateName);
      if (template == null) {
        log.e("Unable to load template {} in assets/templates", templateName);
        return "Unable to load template " + templateName;
      }
      cache.put(templateName, template);
    }
    return renderInternal(template, models);
  }

  public static String renderInternal(String template, Map<String, Object> model) {
    StringBuilder result = new StringBuilder();
    int start = 0;
    while (true) {
      int stop = template.indexOf("${", start);
      if (stop >= 0) {
        result.append(template, start, stop);
        int end = template.indexOf('}', stop + 2);
        String key = template.substring(stop + 2, end).trim();
        Object o = model.get(key);
        result.append(o);
        start = end + 1;
      } else {
        result.append(template, start, template.length());
        break;
      }
    }
    return result.toString();
  }


  private static String loadTemplate(String templateName) {
    BufferedSource source = null;
    try {
      InputStream in = TemplateEngine.class.getClassLoader().getResourceAsStream("templates/" + templateName);
      if(in == null) return null;
      source = Okio.buffer(Okio.source(in));
      return source.readUtf8();
    } catch (IOException e) {
      log.e(e);
    } finally {
      Util.closeQuietly(source);
    }
    return null;
  }
}